package com.voe;

import com.voe.callback.VoiceEngineObserver;
import com.voe.common.NetEqBgnModes;
import com.voe.common.NetEqModes;
import com.voe.common.OnHoldModes;
import com.voe.common.OutputParam;
import com.voe.common.ReturnValue;
import com.voe.common.Utility;

/** This sub-API supports the following functionalities:<br/>
*<br/>
*- Enables full duplex VoIP sessions via RTP using G.711 (mu-Law or A-Law).<br/>
*- Initialization and termination.<br/>
*- Trace information on text files or via callbacks.<br/>
*- Multi-channel support (mixing, sending to multiple destinations etc.).<br/>
*- Call setup (port and address) for receiving and sending sides.<br/>
*<br/>
*To support other codecs than G.711, the VoECodec sub-API must be utilized.<br/>
*<br/>
*Usage example, omitting error checking:<br/>
*<br/>
*VoiceEngine voe = VoiceEngine.createInstance();<br/>
*VoEBase base = VoEBase.createInstance(voe);<br/>
*base.init();<br/>
*int ch = base.createChannel();<br/>
*base.startPlayout(ch);<br/>
*...<br/>
*base.deleteChannel(ch);<br/>
*base.terminate();<br/>
*base.release();<br/>
*voe.release();<br/>
*/
public class VoEBase {
	
	//[start] apis

	public static VoEBase createInstance(VoiceEngine voiceEngine) {

		long p = GetInterface(voiceEngine._p);
		if(p != 0)
			return new VoEBase(p);
		return null;
	}

	public void release() {
		if (_p != 0) {
			Release(_p);
		}
	}
	
	/** Installs the observer class to enable runtime error control and<br/>
	 *  warning notifications.
	 */
	public int registerVoiceEngineObserver(VoiceEngineObserver observer) {
		Utility.throwNullPointerException(observer, "observer");
		return RegisterVoiceEngineObserver(_p, observer);
	}

	/** Removes and disables the observer class for runtime error control<br/>
	 *  and warning notifications.
	 */
	public int deRegisterVoiceEngineObserver() {
		return DeRegisterVoiceEngineObserver(_p);
	}

	/** Initiates all common parts of the VoiceEngine; e.g. all<br/>
	 *  encoders/decoders, the sound card and core receiving components.<br/>
	 *  This method also makes it possible to install a user-defined<br/>
	 *  external Audio Device Module (ADM) which implements all the audio<br/>
	 *  layer functionality in a separate (reference counted) module.
	 */
	public int init(AudioDeviceModule external_adm) {
		return Init(_p, external_adm);
	}

	/** Initiates all common parts of the VoiceEngine; e.g. all<br/>
	 *  encoders/decoders, the sound card and core receiving components.<br/>
	 *  This method also makes it possible to install a user-defined<br/>
	 *  external Audio Device Module (ADM) which implements all the audio<br/>
	 *  layer functionality in a separate (reference counted) module.
	 */
	public int init() {
		return init(null);
	}

	/** Terminates all VoiceEngine functions and releses allocated resources.
	 */
	public int terminate() {
		return Terminate(_p);
	}

	/** Retrieves the maximum number of channels that can be created.
	 */
	public int maxNumOfChannels() {
		return MaxNumOfChannels(_p);
	}

	/** Creates a new channel and allocates the required resources for it.
	 */
	public int createChannel() {
		return CreateChannel(_p);
	}

	/** Deletes an existing channel and releases the utilized resources.
	 */
	public int deleteChannel(int channel) {
		return DeleteChannel(_p, channel);
	}

	/** Sets the local receiver port and address for a specified<br/>
	 *  |channel| number.
	 */
	public int setLocalReceiver(int channel, int port,
			int RTCPport, String ipAddr, String multiCastAddr) {
		return SetLocalReceiver(_p, channel, port, RTCPport, ipAddr, multiCastAddr);
	}

	/** Sets the local receiver port and address for a specified<br/>
	 *  |channel| number.
	 */
	public int setLocalReceiver(int channel, int port,
			int RTCPport, String ipAddr) {
		return setLocalReceiver(channel, port, RTCPport, ipAddr, null);
	}

	/** Sets the local receiver port and address for a specified<br/>
	 *  |channel| number.
	 */
	public int setLocalReceiver(int channel, int port,
			int RTCPport) {
		return setLocalReceiver(channel, port, RTCPport, null, null);
	}

	/** Sets the local receiver port and address for a specified<br/>
	 *  |channel| number.
	 */
	public int setLocalReceiver(int channel, int port) {
		return setLocalReceiver(channel, port, -1, null, null);
	}

	/** Gets the local receiver port and address for a specified<br/>
	 *  |channel| number.
	 */
	public int getLocalReceiver(int channel, ReturnValue<Integer> port, ReturnValue<Integer> RTCPport, ReturnValue<String> ipAddr) {
		OutputParam output = new OutputParam();
		int result = GetLocalReceiver(_p, channel, output);
		if(result == 0) {
			port.setValue((Integer) output.getObject()[0]);
			RTCPport.setValue((Integer) output.getObject()[1]);
			ipAddr.setValue((String) output.getObject()[2]);
		}
		return result;
	}

	/** Sets the destination port and address for a specified |channel| number.
	 */
	public int setSendDestination( int channel, int port, String ipAddr, 
			int sourcePort, int RTCPport) {
		return SetSendDestination(_p, channel, port, ipAddr, sourcePort, RTCPport);
	}

	/** Sets the destination port and address for a specified |channel| number.
	 */
	public int setSendDestination( int channel, int port, String ipAddr, 
			int sourcePort) {
		return setSendDestination(channel, port, ipAddr, sourcePort, -1);
	}

	/** Sets the destination port and address for a specified |channel| number.
	 */
	public int setSendDestination( int channel, int port, String ipAddr) {
		return setSendDestination(channel, port, ipAddr, -1, -1);
	}

	/** Gets the destination port and address for a specified |channel| number.
	 */
	public int getSendDestination(int channel, ReturnValue<Integer> port, ReturnValue<String> ipAddr, ReturnValue<Integer> sourcePort, ReturnValue<Integer> RTCPport) {
		OutputParam output = new OutputParam();
		int result = GetSendDestination(_p, channel, output);
		if(result == 0) {
			port.setValue((Integer) output.getObject()[0]);
			ipAddr.setValue((String) output.getObject()[1]);
			sourcePort.setValue((Integer) output.getObject()[2]);
			RTCPport.setValue((Integer) output.getObject()[3]);
		}
		return result;
	}

	/** Prepares and initiates the VoiceEngine for reception of<br/>
	 *  incoming RTP/RTCP packets on the specified |channel|.
	 */
	public int startReceive(int channel) {
		return StartReceive(_p, channel);
	}

	/** Stops receiving incoming RTP/RTCP packets on the specified |channel|.
	 */
	public int stopReceive(int channel) {
		return StopReceive(_p, channel);
	}

	/** Starts forwarding the packets to the mixer/soundcard for a<br/>
	 *  specified |channel|.
	 */
	public int startPlayout(int channel) {
		return StartPlayout(_p, channel);
	}

	/** Stops forwarding the packets to the mixer/soundcard for a<br/>
	 *  specified |channel|.
	 */
	public int stopPlayout(int channel) {
		return StopPlayout(_p, channel);
	}

	/** Starts sending packets to an already specified IP address and<br/>
	 *  port number for a specified |channel|.
	 */
	public int startSend(int channel) {
		return StartSend(_p, channel);
	}

	/** Stops sending packets from a specified |channel|.
	 */
	public int stopSend(int channel) {
		return StopSend(_p, channel);
	}

	/** Gets the version information for VoiceEngine and its components.
	 */
	public String getVersion() {
		return GetVersion(_p);
	}

	/** Gets the last VoiceEngine error code.
	 */
	public int lastError() {
		return LastError(_p);
	}

	/** Stops or resumes playout and transmission on a temporary basis.
	 */
	public int setOnHoldStatus(int channel, boolean enable, OnHoldModes mode) {
		return SetOnHoldStatus(_p, channel, enable, mode.getValue());
	}

	/** Stops or resumes playout and transmission on a temporary basis.
	 */
	public int setOnHoldStatus(int channel, boolean enable) {
		return setOnHoldStatus(channel, enable, OnHoldModes.kHoldSendAndPlay);
	}

	/** Gets the current playout and transmission status.
	 */
	public int getOnHoldStatus(int channel, ReturnValue<Boolean> enabled, ReturnValue<OnHoldModes> mode) {
		OutputParam output = new OutputParam();
		int result = GetOnHoldStatus(_p, channel, output);
		if(result == 0) {
			enabled.setValue((Boolean) output.getObject()[0]);
			mode.setValue(OnHoldModes.fromValue((Integer) output.getObject()[1]));
		}
		return result;
	}
	

	/** Sets the NetEQ playout mode for a specified |channel| number.
	 */
	public int setNetEQPlayoutMode(int channel, NetEqModes mode) {
		return SetNetEQPlayoutMode(_p, channel, mode.getValue());
	}

	/** Gets the NetEQ playout mode for a specified |channel| number.
	 */
	public int getNetEQPlayoutMode(int channel, ReturnValue<NetEqModes> mode) {
		OutputParam output = new OutputParam();
		int result = GetNetEQPlayoutMode(_p, channel, output);
		if(result == 0) {
			mode.setValue(NetEqModes.fromValue((Integer) output.getObject()[0]));
		}
		return result;
	}

	/** Sets the NetEQ background noise mode for a specified |channel| number.
	 */
	public int setNetEQBGNMode(int channel, NetEqBgnModes mode) {
		return SetNetEQBGNMode(_p, channel, mode.getValue());
	}

	/** Gets the NetEQ background noise mode for a specified |channel| number.
	 */
	public int getNetEQBGNMode(int channel, ReturnValue<NetEqBgnModes> mode) {
		OutputParam output = new OutputParam();
		int result = GetNetEQBGNMode(_p, channel, output);
		if(result == 0) {
			mode.setValue(NetEqBgnModes.fromValue((Integer) output.getObject()[0]));
		}
		return result;
	}

	protected VoEBase(long p) {
		_p = p;
	}

	protected long _p;
	
	//[end]
	
	
	
	
	
	

	// [start] jni api

	// Factory for the VoEBase sub-API. Increases an internal reference
	// counter if successful. Returns NULL if the API is not supported or if
	// construction fails.
	private static native long GetInterface(long p_voiceEngine);

	// Releases the VoEBase sub-API and decreases an internal reference
	// counter. Returns the new reference count. This value should be zero
	// for all sub-API:s before the VoiceEngine object can be safely deleted.
	private static native int Release(long p_voeBase);

	// Installs the observer class to enable runtime error control and
	// warning notifications.
	private static native int RegisterVoiceEngineObserver(long p_voeBase,
			VoiceEngineObserver observer);

	// Removes and disables the observer class for runtime error control
	// and warning notifications.
	private static native int DeRegisterVoiceEngineObserver(long p_voeBase);

	// Initiates all common parts of the VoiceEngine; e.g. all
	// encoders/decoders, the sound card and core receiving components.
	// This method also makes it possible to install a user-defined
	// external Audio Device Module (ADM) which implements all the audio
	// layer functionality in a separate (reference counted) module.
	private static native int Init(long p_voeBase,
			AudioDeviceModule external_adm);

	// Terminates all VoiceEngine functions and releses allocated resources.
	private static native int Terminate(long p_voeBase);

	// Retrieves the maximum number of channels that can be created.
	private static native int MaxNumOfChannels(long p_voeBase);

	// Creates a new channel and allocates the required resources for it.
	private static native int CreateChannel(long p_voeBase);

	// Deletes an existing channel and releases the utilized resources.
	private static native int DeleteChannel(long p_voeBase, int channel);

	// Sets the local receiver port and address for a specified
	// |channel| number.
	private static native int SetLocalReceiver(long p_voeBase, int channel,
			int port, int RTCPport, String ipAddr, String multiCastAddr);

	// Gets the local receiver port and address for a specified
	// |channel| number.
	private static native int GetLocalReceiver(long p_voeBase, int channel,
			OutputParam output);

	// Sets the destination port and address for a specified |channel| number.
	private static native int SetSendDestination(long p_voeBase, int channel,
			int port, String ipAddr, int sourcePort, int RTCPport);

	// Gets the destination port and address for a specified |channel| number.
	private static native int GetSendDestination(long p_voeBase, int channel,
			OutputParam output);

	// Prepares and initiates the VoiceEngine for reception of
	// incoming RTP/RTCP packets on the specified |channel|.
	private static native int StartReceive(long p_voeBase, int channel);

	// Stops receiving incoming RTP/RTCP packets on the specified |channel|.
	private static native int StopReceive(long p_voeBase, int channel);

	// Starts forwarding the packets to the mixer/soundcard for a
	// specified |channel|.
	private static native int StartPlayout(long p_voeBase, int channel);

	// Stops forwarding the packets to the mixer/soundcard for a
	// specified |channel|.
	private static native int StopPlayout(long p_voeBase, int channel);

	// Starts sending packets to an already specified IP address and
	// port number for a specified |channel|.
	private static native int StartSend(long p_voeBase, int channel);

	// Stops sending packets from a specified |channel|.
	private static native int StopSend(long p_voeBase, int channel);

	// Gets the version information for VoiceEngine and its components.
	private static native String GetVersion(long p_voeBase);

	// Gets the last VoiceEngine error code.
	private static native int LastError(long p_voeBase);

	// Stops or resumes playout and transmission on a temporary basis.
	private static native int SetOnHoldStatus(long p_voeBase, int channel,
			boolean enable, int mode);

	// Gets the current playout and transmission status.
	private static native int GetOnHoldStatus(long p_voeBase, int channel,
			OutputParam output);

	// Sets the NetEQ playout mode for a specified |channel| number.
	private static native int SetNetEQPlayoutMode(long p_voeBase, int channel,
			int mode);

	// Gets the NetEQ playout mode for a specified |channel| number.
	private static native int GetNetEQPlayoutMode(long p_voeBase, int channel,
			OutputParam output);

	// Sets the NetEQ background noise mode for a specified |channel| number.
	private static native int SetNetEQBGNMode(long p_voeBase, int channel,
			int mode);

	// Gets the NetEQ background noise mode for a specified |channel| number.
	private static native int GetNetEQBGNMode(long p_voeBase, int channel,
			OutputParam output);

	// [end]
}
